import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

/**
 * my first test for java 1.6 mustang/ ScriptEngine
 * @author Pierre Lindenbaum PhD
 *
 * example: cat *.fasta | java org.lindenb.sandox.FastaAWK "FastaAWK.gcPercent(sequence)<0.45 || (sequence.length>900) || (FastaAWK .reverseComplement(sequence).toUpperCase().indexOf('ATGCTTCTTG')!=-1 && name.indexOf('Xenopus')!=-1 );"
 *
 */
public class FastaAWK {
        /** header of fasta sequence */
        private String name=null;
        /** dna sequence */
        private StringBuilder sequence= new StringBuilder();
        /** compiled user script */
        private CompiledScript compiledScript=null;


        /** constructor
         * initialize the statements
         * @param statements
         */
        public FastaAWK(String args[]) throws ScriptException
                {
                //copy statements to add the 'importClass'
                String statements[]= new String[args.length+1];
                //import this class to get a handle on gcPercent and reverseComplement
                statements[0]="importClass(Packages."+this.getClass().getName()+");";
                System.arraycopy(args, 0, statements, 1, args.length);

                //get a javascript engine
                ScriptEngineManager sem = new ScriptEngineManager();
                ScriptEngine scriptEngine = sem.getEngineByName("js");
                ScriptEngineFactory scriptEngineFactory= scriptEngine.getFactory();
                 String program = scriptEngineFactory.getProgram(statements);
                //compile this program
                 this.compiledScript=((Compilable) scriptEngine).compile(program);
                }

        /**
         *
         * @param sequence  the dna sequence
         * @return the GC%
         */
        public static double gcPercent(String sequence)
                {
                int n=0;
                for(int i=0;i< sequence.length();++i)
                        {
                        char base= Character.toUpperCase(sequence.charAt(i));
                        n+=(base=='G' || base=='C'?1:0);
                        }
                return (double)(n/(double)sequence.length());
                }

        /**
         * return the reverse complement of a sequence
         * @param sequence the dna sequence
         * @return  the reverse complement of a sequence
         */
        public static String reverseComplement(String sequence)
                {
                StringBuilder b= new StringBuilder();
                for(int i=sequence.length()-1;i>=0;--i)
                        {
                        switch(sequence.charAt(i))
                                {
                                case 'A': b.append('T');break;
                                case 'T': b.append('A');break;
                                case 'G': b.append('C');break;
                                case 'C': b.append('G');break;
                                case 'a': b.append('t');break;
                                case 't': b.append('a');break;
                                case 'g': b.append('c');break;
                                case 'c': b.append('g');break;
                                default: b.append('N');break;
                                }
                        }

                return b.toString();
                }

        /**
         * print the current fasta sequence if the compiled script return true
         * @throws ScriptException
         */
        public void eval() throws ScriptException
                {
                /* bind name and sequence to javascript variable 'name' and 'seq
uence'*/
                SimpleBindings bindings= new SimpleBindings();
                bindings.put("name", this.name);
                bindings.put("sequence", this.sequence.toString());
                //invoke the script with the current binding and get the result
                Object o=this.compiledScript.eval(bindings);
                if(o==null || !(o instanceof Boolean ) ) return;
                //if the result is true: print the fasta sequence
                Boolean b=(Boolean)o;
                if(b.equals(Boolean.FALSE))
                        {
                        return;
                        }
                System.out.print(name);
                for(int i=0;i< sequence.length();++i)
                        {
                        if(i%50==0) System.out.println();
                        System.out.print(sequence.charAt(i));
                        }
                System.out.println();

                }

        /**
         * @param args
         */
        public static void main(String[] args)
                {
                try {
                        FastaAWK awk= new FastaAWK(args);
                        //loop over fasta sequences
                        BufferedReader in= new BufferedReader(new InputStreamReader(System.in));
                        String line=null;
                        while((line=in.readLine())!=null)
                                {
                                if(line.startsWith(">"))
                                        {
                                        if(awk.sequence.length()>0)
                                                {
                                                awk.eval();
                                                }
                                        awk.sequence.setLength(0);
                                        awk.name=line.trim();
                                        }
                                else
                                        {
                                        awk.sequence.append(line.trim());
                                        }
                                }
                        if(awk.sequence.length()>0)
                                {
                                awk.eval();
                                }

                        in.close();
                        }
                catch (Throwable e)
                        {
                        e.printStackTrace();
                        }

                }

}
